package com.cskaoyan.search.service.Impl;

import com.cskaoyan.mall.dto.ProductDto;
import com.cskaoyan.search.converter.ProductConverter;
import com.cskaoyan.search.dto.SearchResponse;
import com.cskaoyan.search.entity.ItemDocument;
import com.cskaoyan.search.form.SearchRequest;
import com.cskaoyan.search.service.ProductSearchService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * \* User: 余雨健
 * \* Date: 2022/11/4
 * \* Time: 14:14
 **/
@Service
public class ProductSearchServiceImpl implements ProductSearchService {
    @Autowired
    ElasticsearchRestTemplate restTemplate;

    @Autowired
    ProductConverter productConverter;

    @Override
    public SearchResponse search(SearchRequest request) {
        //该Builder包含所有搜索请求的参数
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //获取bool查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //构造bool查询中的match查询
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title",request.getKey());
        boolQueryBuilder.must(matchQuery);
        //构造bool查询中的范围查询
        RangeQueryBuilder priceRange = QueryBuilders.rangeQuery("price");
        priceRange.gte(request.getPriceGt());
        priceRange.lte(request.getPriceLte());
        boolQueryBuilder.filter(priceRange);
        //将bool查询添加到NativeSearchQueryBuilder
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        PageRequest of = null;
        if(request.getSort() != ""){
            if (Integer.parseInt(request.getSort()) == 1) {
                Sort sort = Sort.by(Sort.Direction.ASC, "price");
                of = PageRequest.of(request.getPage() - 1, request.getSize(),sort);
            } else if (Integer.parseInt(request.getSort()) == -1) {
                Sort sort = Sort.by(Sort.Direction.DESC, "price");
                of = PageRequest.of(request.getPage() - 1, request.getSize(),sort);
            }
        }else {
            of = PageRequest.of(request.getPage() - 1, request.getSize());
        }
        // 向NativeSearchQueryBuilder添加分页参数
        nativeSearchQueryBuilder.withPageable(of);
        //构造高亮参数
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").preTags("<font color='red'>").postTags("</font>");
        // 向NativeSearchQueryBuilder添加高亮参数
        nativeSearchQueryBuilder.withHighlightBuilder(highlightBuilder);
        // 使用ElasticsearchRestTemplate发起搜索请求
        NativeSearchQuery build = nativeSearchQueryBuilder.build();
        SearchHits<ItemDocument> search = restTemplate.search(build, ItemDocument.class);
        //获取满足条件的文档数量
        long totalHits = search.getTotalHits();
        List<SearchHit<ItemDocument>> searchHits = search.getSearchHits();
        ArrayList<ProductDto> productDtos = new ArrayList<>();
        for (SearchHit<ItemDocument> searchHit : searchHits) {
            ItemDocument content = searchHit.getContent();
            List<String> title = searchHit.getHighlightField("title");
            content.setTitle(title.get(0));
            ProductDto productDto = productConverter.item2Dto(content);
            productDtos.add(productDto);
        }
        SearchResponse<ProductDto> searchResponse = new SearchResponse<>();
        searchResponse.setData(productDtos);
        searchResponse.setTotal(totalHits);
        return searchResponse;
    }

    @Override
    public SearchResponse fuzzySearch(SearchRequest request){
        //该Builder包含所有搜索请求的参数
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //构造具体查询
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", request.getKey());
        //将match查询添加到nativeSearchQueryBuilder
        nativeSearchQueryBuilder.withQuery(matchQueryBuilder);
        //构造分页查询
        PageRequest of = PageRequest.of(request.getPage(), request.getSize());
        //将page添加到nativeSearchQueryBuilder
        nativeSearchQueryBuilder.withPageable(of);
        //构造高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").preTags("<font color='red'>").postTags("</font>");
        //将highlight添加到nativeSearchQueryBuilder
        nativeSearchQueryBuilder.withHighlightBuilder(highlightBuilder);
        //使用restTemplate发起请求
        NativeSearchQuery build = nativeSearchQueryBuilder.build();
        SearchHits<ItemDocument> search = restTemplate.search(build, ItemDocument.class);
        //获取搜索到的文档数量
        long totalHits = search.getTotalHits();
        List<SearchHit<ItemDocument>> searchHits = search.getSearchHits();
        ArrayList<ProductDto> productDtos = new ArrayList<>();
        for (SearchHit<ItemDocument> searchHit : searchHits) {
            // 获取命中的文档
            ItemDocument content = searchHit.getContent();
            ProductDto productDto = productConverter.item2Dto(content);
            productDtos.add(productDto);
        }
        SearchResponse<ProductDto> searchResponse = new SearchResponse<>();
        searchResponse.setData(productDtos);
        searchResponse.setTotal(totalHits);
        return searchResponse;
    }
}
